/**
 *
 */
package hichecker.ui.custom_views.requirement;

import hichecker.controller.Config;
import hichecker.ui.components.custom_table.AbstractCustomTableModel;
import hichecker.ui.components.custom_table.column_class.Grade;
import hichecker.ui.components.custom_table.column_class.Points;
import hichecker.university.PTL;
import hichecker.university.PTLSeries;
import hichecker.university.PVL;
import hichecker.university.PVLSeries;
import hichecker.university.Requirement;
import hichecker.university.Series;
import hichecker.university.Student;

import java.util.ArrayList;
import java.util.List;

/**
 *
 */
public class RequirementViewTableModel extends AbstractCustomTableModel<String> {

	private Requirement requirement;
	private List<Series> series = new ArrayList<Series>();
	private List<Student> students;
	private List<Column> dynamicColumns = new ArrayList<Column>();
	private enum Column {POINTS, GRADE, SUM_POINTS, SUM_GRADE};

	public int FIXED_COLUMNS = 4;

	public RequirementViewTableModel(Requirement requirement, List<Student> students) {
		this.requirement = requirement;
		this.students = students;

		if (requirement instanceof PVL)
			for (PVLSeries ser : ((PVL) requirement).getSeries()) {
				series.add(ser);
				dynamicColumns.add(Column.POINTS);
			}

		if (requirement instanceof PTL)
			for (PTLSeries ser : ((PTL) requirement).getSeries()) {
				series.add(ser);
				dynamicColumns.add(Column.GRADE);
			}

		if (series.size() > 0) {
			dynamicColumns.add(Column.SUM_POINTS);
			if (requirement instanceof PTL)
				dynamicColumns.add(Column.SUM_GRADE);
		}
	}

	@Override
	public boolean isCellEditable(int row, int column) {
		return column < FIXED_COLUMNS;
	}

	@Override
	public void setValueAt(Object value, int row, int column) {

		// Check if were at the last line. It's the case if all values are null
		boolean lastLine = row >= students.size();
		if (lastLine) {
			addRow();
		}

		Student curStudent;
		curStudent = students.get(row);

		switch (column) {
		case 0:
			curStudent.setLastName("" + value);
			break;
		case 1:
			curStudent.setFirstName("" + value);
			break;
		case 2:
			curStudent.setMatrikel("" + value);
			break;
		case 3:
			curStudent.setStudyCourse("" + value);
			break;
		}

		if (column < FIXED_COLUMNS) fireTableCellUpdated(row, column);
	}

	public void addRow() {
		students.add(new Student());
		fireTableRowsInserted(getRowCount() - 1, getRowCount() - 1);
	}

	public void deleteRow(int row) {
		if (row < students.size()) {
			students.remove(row);
			fireTableDataChanged();
		}
	}

	@Override
	protected String getRowID(int row) {
		if (row >= students.size()) return null;
		return "" + students.get(row).getID();
	}

	@Override
	public Object getValueAt(int row, int column) {
		// Letzt Zeile => alles leer
		if (row == getRowCount() - 1) return null;
		// Bereichsüberschreitung
		if (row >= getRowCount() || column >= getColumnCount()) return null;

		Student curStudent = students.get(row);
		// Standardspalte
		switch(column) {
			case 0: return curStudent.getLastName();
			case 1: return curStudent.getFirstName();
			case 2: return curStudent.getMatrikel();
			case 3: return curStudent.getStudyCourse();
		}

		// Dynamische Spalten durchgehen
		column -= FIXED_COLUMNS;
		if (column >= dynamicColumns.size()) return null;

		switch (dynamicColumns.get(column)) {
			case POINTS:
				float check = series.get(column).getSumGainedPoints(curStudent);
				return check < 0 ? "" : check;
			case GRADE:
				check = ((PTLSeries) series.get(column)).getGrade(curStudent);
				return check < 0 ? "" : check;
			case SUM_POINTS:
				check = requirement.getSumPoints(curStudent);
				return check < 0 ? "" : check;
			case SUM_GRADE:
				check = ((PTL) requirement).getGrade(curStudent);
				return check < 0 ? "" : check;
			default: return null;
		}
	}

	@Override
	public int getColumnCount() {
		return FIXED_COLUMNS + dynamicColumns.size();
	}

	@Override
	public int getRowCount() {
		return students.size() + 1;
	}

	@Override
	public Class<?> getColumnClass(int column) {
		if (column < FIXED_COLUMNS)
			return column == 2 ? Integer.class : Object.class;
		column -= FIXED_COLUMNS;

		if (column >= dynamicColumns.size())
			return Object.class;

		switch (dynamicColumns.get(column)) {
			case POINTS: return Points.class;
			case GRADE: return Grade.class;
			case SUM_POINTS: return Points.class;
			case SUM_GRADE: return Grade.class;
			default: return Object.class;
		}
	}

	@Override
	public Object[] getHeaderValues() {
		headerValues = new Object[getColumnCount()];

		// The student data field
		headerValues[0] = "<html><br>" + Config.STUDENT_LAST_NAME + "</html>";
		headerValues[1] = "<html><br>" + Config.STUDENT_FIRST_NAME + "</html>";
		headerValues[2] = "<html><br>" + Config.STUDENT_MATRIKEL + "</html>";
		headerValues[3] = "<html><br>" + Config.STUDENT_STUDY_COURSE + "</html>";

		// If the requirement is a PVL
		if (requirement instanceof PVL) {
			List<PVLSeries> seriesList = ((PVL) requirement).getSeries();
			for (int i = 0; i < seriesList.size(); i++) {
				PVLSeries series = seriesList.get(i);
				headerValues[i+4] = "<html>" + series.getName() + "<br>" + series.getSumMax() + "</html>";
			}
			if (seriesList.size() > 0)
				headerValues[getColumnCount() - 1] = "<html>∑<br>" + ((PVL) requirement).getMaxPoints() + "</html>";
		}

		// If the requirement is a PTL
		if (requirement instanceof PTL) {
			List<PTLSeries> seriesList = ((PTL) requirement).getSeries();
			for (int i = 0; i < seriesList.size(); i++) {
				PTLSeries series = seriesList.get(i);
				headerValues[i+4] = "<html>" + series.getName() + "<br>" + series.getSumMax() + "</html>";
			}
			if (seriesList.size() > 0) {
				headerValues[getColumnCount() - 2] = "<html>∑<br>" + ((PTL) requirement).getMaxPoints() + "</html>";
				headerValues[getColumnCount() - 1] = "<html><br>" + Config.REQUIREMENT_GRADE + "</html>";
			}
		}
		return headerValues;
	}
}
